home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 25
/
Aminet 25 (1998)(GTI - Schatztruhe)[!][Jun 1998].iso
/
Aminet
/
util
/
arc
/
mpackWOS.lha
/
mpackppc
/
src
/
os2os.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-04-08
|
10KB
|
442 lines
/* (C) Copyright 1993,1994 by Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of Carnegie
* Mellon University not be used in advertising or publicity
* pertaining to distribution of the software without specific,
* written prior permission. Carnegie Mellon University makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied
* warranty.
*
* CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#define INCL_DOSFILEMGR
#define INCL_DOSERRORS
#include <os2.h>
#include <stdio.h>
#include <io.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "xmalloc.h"
#include "common.h"
#ifdef __EMX__ /* This is for EMX + GCC */
#define EACCESS EACCES
#else /* This is for IBM C++ */
#include <direct.h>
#define ENAMETOOLONG EOS2ERR
#endif /* EMX or IBM CSet++ */
int overwrite_files = 0;
int didchat;
int mime_eas = 0;
/* The name of the file we're writing */
static char *output_fname = 0;
/* Characters that can be in filenames */
#define GOODCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" \
"0123456789-_^$~!#%&{}@`'()"
int my_mkdir(char *filename)
{
PEAOP2 EABuf;
APIRET rc;
EABuf = 0;
rc = DosCreateDir(filename,EABuf);
switch (rc) {
case NO_ERROR:
return 0;
case ERROR_FILENAME_EXCED_RANGE:
errno = EACCESS;
return 1;
case ERROR_PATH_NOT_FOUND:
errno = ENOENT;
return -1;
default:
errno = EACCESS;
return -1;
}
}
void crunch_file(char *p, char **q)
{
int len, sawdot;
for (*q=p, len=sawdot=0; *p; p++) {
if (*p == '.') {
if (!sawdot) {
*(*q)++ = '.';
sawdot++;
len = 0;
}
} else if (len < (sawdot ? 3:8)) {
*(*q)++ = *p;
len++;
}
}
**q = '\0';
}
typedef struct
{
ULONG cbList;
ULONG oNext;
BYTE fEA;
BYTE cbName;
USHORT cbValue;
BYTE NameBuffer[CCHMAXPATH*2+8];
}
FEALST;
void EA_attach(int fd, char *name, char *value)
{
EAOP2 eaop;
FEALST fealst;
int len;
eaop.fpFEA2List = (PFEA2LIST) &fealst;
eaop.fpGEA2List = NULL;
eaop.oError = 0;
fealst.oNext = 0;
fealst.fEA = 0;
fealst.cbName = strlen(name) ;
fealst.cbValue = strlen(value) +4;
len = fealst.cbName +1;
strcpy(fealst.NameBuffer,name);
*((USHORT *) &(fealst.NameBuffer [len])) = 0xFFFD;
len += sizeof(USHORT);
*((USHORT *) &(fealst.NameBuffer [len])) = strlen(value);
len += sizeof(USHORT);
strcpy(&(fealst.NameBuffer[len]), value);
fealst.cbList = fealst.cbName+fealst.cbValue+9;
DosSetFileInfo(fd, FIL_QUERYEASIZE, &eaop, sizeof(eaop));
}
/* Generate a message-id */
char *os_genid()
{
static time_t curtime;
static char *hostname;
static char *domain;
char *result;
if (curtime == 0) {
time(&curtime);
hostname = getenv("HOSTNAME");
if (!hostname) hostname="random-pc";
domain = getenv("DOMAINNAME");
if (!domain) domain="random-domain";
}
if (strchr(hostname,'.')) {
result = xmalloc(25+strlen(hostname));
sprintf(result, "%lu@%s", curtime++, hostname);
} else {
if (domain[0] == '.') domain++;
result = xmalloc(25+strlen(hostname)+strlen(domain));
sprintf(result, "%lu@%s.%s", curtime++, hostname, domain);
}
return result;
}
/* Create and return directory for a message-id */
char *os_idtodir(id)
char *id;
{
static char buf[512];
int len = 0;
int cs = 0;
int rc;
char *p, *q;
if (p = getenv("TMP")) {
strncpy(buf, p, 201);
p[200] = '\0'; /* Ensure sufficiently short */
}
else {
strcpy(buf, "\\tmp");
(void)my_mkdir(buf);
}
if (buf[strlen(buf)-1] != '\\')
strcat(buf, "\\");
strcat(buf, "parts");
(void)my_mkdir(buf);
p = buf + strlen(buf);
*p++ = '\\';
q = p;
while (*id && len < 200) {
if (strchr(GOODCHARS, *id)) {
*p++ = *id;
len++;
cs += *id * len;
}
id++;
}
*p = '\0';
rc = my_mkdir(buf);
if (rc == 1) {
char csarr[] = GOODCHARS;
/* maybe 8.3 restriction. Take 8 char + 3 checksum */
p = q;
len = 0;
while ( *p && len < 8) { len++; p++; }
*p++ = '.';
*p++ = csarr[cs % sizeof(csarr)];
cs = cs / sizeof(csarr);
*p++ = csarr[cs % sizeof(csarr)];
cs = cs / sizeof(csarr);
*p++ = csarr[cs % sizeof(csarr)];
*p = '\0';
rc = my_mkdir(buf);
}
if ((rc == -1) && (errno != EACCESS)) {
perror(buf);
return 0;
}
*p++ = '\\';
*p = '\0';
return buf;
}
/*
* We are done with the directory returned by os_idtodir()
* Remove it
*/
os_donewithdir(dir)
char *dir;
{
char *p;
/* Remove trailing slash */
p = dir + strlen(dir) - 1;
*p = '\0';
rmdir(dir);
}
/*
* Create a new file, with suggested filename "fname".
* "fname" may have come from an insecure source, so clean it up first.
* It may also be null.
* "contentType" is passed in for use by systems that have typed filesystems.
* "flags" contains a bit pattern describing attributes of the new file.
*/
FILE *os_newtypedfile(fname, contentType, flags, contentParams)
char *fname;
char *contentType;
int flags;
params contentParams;
{
char *p, *q, *r;
int len=0;
int fd=0;
int filesuffix=0;
int uselong=0;
static int partno=0;
char buf[256], lbuf[256];
char *descfname=0;
FILE *outfile = 0;
FILESTATUS3 FileInfoBuf;
if (!fname) fname = "";
/* Chop off any drive specifier, convert / to \ */
if (*fname && fname[1] == ':') fname +=2;
for (p = fname; *p; p++) if (*p == '/') *p = '\\';
/* If absolute path name, chop to tail */
if (*fname == '\\') {
p = strrchr(fname, '\\');
fname = p+1;
}
/* Clean out bad characters, create directories along path */
for (p=q=r=fname; *p; p++) {
if (*p == '\\') {
if (!strncmp(p, "\\..\\", 4)) {
p[1] = p[2] = 'X';
}
*q = '\0';
if (my_mkdir(fname) == 1) {
crunch_file(r,&q);
(void) my_mkdir(fname);
}
*q++ = '\\';
r = q;
}
else if ( (len < 200) && strchr(GOODCHARS ".", *p)) {
*q++ = *p;
len++;
}
}
*q = '\0';
if (!fname[0]) {
sprintf(buf, "part%d",++partno);
fname = buf;
}
do {
errno = 0;
fd = open(fname, O_CREAT | O_RDWR | (overwrite_files ? O_TRUNC : O_EXCL) |
((flags & FILE_BINARY) ? O_BINARY : O_TEXT), S_IREAD | S_IWRITE);
if ((fd == -1) && (errno == ENAMETOOLONG)) {
r = strrchr(fname, '\\');
if (!r) r = fname;
strcpy(lbuf,r);
uselong=1;
crunch_file(r,&q);
fd = open(fname, O_CREAT | O_RDWR | (overwrite_files ? O_TRUNC : O_EXCL) |
((flags & FILE_BINARY) ? O_BINARY : O_TEXT), S_IREAD | S_IWRITE);
}
/* simulate sharing violation, if character device found */
if (fd != -1) {
if (DosQueryFileInfo(fd, FIL_STANDARD, &FileInfoBuf, sizeof(FILESTATUS3))) {
close(fd);
fd = -1;
errno = EACCESS;
}
}
if ((fd == -1) && ((errno == EEXIST) || (errno == EACCESS))) {
/* chop off suffix */
if (fname != buf) {
strcpy(buf,fname);
fname=buf;
}
r = strrchr(fname, '\\');
if (!r) r = fname;
q = strchr(r, '.');
if (q) {
if (*q) *q = '\0';
}
q = fname + strlen(fname);
sprintf(q, ".%d", ++filesuffix);
errno = 0;
}
} while ((fd == -1) && (!errno));
if (fd == -1) {
perror(fname);
} else {
if (uselong) EA_attach(fd,".LONGNAME",lbuf);
if (mime_eas) EA_attach(fd,"MIME-TYPE",contentType);
outfile = fdopen(fd, (flags & FILE_BINARY) ? "wb" : "w");
if (!outfile) {
close(fd);
perror(fname);
}
}
if (output_fname) free(output_fname);
output_fname = strsave(fname);
if (strlen(fname) > sizeof(buf)-6) {
descfname = xmalloc(strlen(fname)+6);
}
else {
descfname = buf;
}
strcpy(descfname, fname);
p = strrchr(descfname, '\\');
if (!p) p = descfname;
if (p = strrchr(p, '.')) *p = '\0';
strcat(descfname, ".dsc");
(void) rename(TEMPFILENAME, descfname);
if (descfname != buf) free(descfname);
fprintf(stdout, "%s (%s)\n", output_fname, contentType);
didchat = 1;
return outfile;
}
/*
* Close a file opened by os_newTypedFile()
*/
os_closetypedfile(outfile)
FILE *outfile;
{
fclose(outfile);
}
/*
* (Don't) Handle a BinHex'ed file
*/
int
os_binhex(infile, part, nparts)
FILE *infile;
int part;
int nparts;
{
return 1;
}
/*
* Warn user that the MD5 digest of the last file created by os_newtypedfile()
* did not match that supplied in the Content-MD5: header.
*/
os_warnMD5mismatch()
{
char *warning;
warning = xmalloc(strlen(output_fname) + 100);
sprintf(warning, "%s was corrupted in transit",
output_fname);
warn(warning);
free(warning);
}
/*
* Report an error (in errno) concerning a filename
*/
os_perror(file)
char *file;
{
perror(file);
}